#include "server.hpp"
#include <unistd.h>
//DataManager *_data;
Service::Service()
{
    Config *config=Config::GetConfigObj();
    _server_port=config->GetServerPort();
    _server_ip=config->GetServerIp();
    _download_prefix=config->GetDownloadPrefix();
}

void Service::Upload(const httplib::Request &req, httplib::Response &rsp)
{
    auto ret=req.has_file("file");
    if(ret==false)
    {
        cout<<__FILE__<<"-"<<__LINE__<<":"<<"Upload():error"<<endl;
        rsp.status=400;
        return;
    }
    const auto &file=req.get_file_value("file");
    string back_dir=Config::GetConfigObj()->GetBackDir();
    string realpath=back_dir+cloudBackup::FileUtil(file.filename).FileName();
    cloudBackup::FileUtil fu(realpath);
    fu.SetContent(file.content);

    BackupInfo info;
    info.NewBackupInfo(realpath);

    cout<<__FILE__<<"-"<<__LINE__<<":"<<"Upload():成功"<<endl;
    _data->Insert(info);
}

void Service::ListShow(const httplib::Request &req, httplib::Response &rsp)
{
    vector<BackupInfo> arry;
    _data->GetAll(&arry);

    stringstream ss;
    ss << "<html><head><title>Download</title></head>";
	ss << "<body><h1>Download</h1><table>";
    for(auto &a:arry)
    {
        ss<<"<tr>";
        string filename=cloudBackup::FileUtil(a.real_path).FileName();
        ss << "<td><a href='" << a.url << "'>" << filename << "</a></td>";
		ss << "<td align='right'>" << ctime(&a.mtime) << "</td>";
		ss << "<td align='right'>" << a.fsize / 1024 << "k</td>";
        ss << "</tr>";
    }
    ss << "</table></body></html>";
    rsp.body=ss.str();
    rsp.set_header("Content-Type", "text/html");
    
    rsp.status=200;
    return;
}

void Service::Download(const httplib::Request &req, httplib::Response &rsp)
{
    //先获取路径(url)
    BackupInfo bi;
    _data->GetOneByRealPath(req.path,&bi);
    //判断是否压缩。压缩泽解压缩，放入备份路径下，然后删除压缩文件
    if(bi.pack_flag==true)
    {
        cloudBackup::FileUtil fu(bi.pack_path);
        fu.UnCompress(bi.real_path);
        remove(bi.pack_path.c_str());
        bi.pack_flag=false;
        _data->Updata(bi);
    }

    //断点继传-先判断是是否有 if-Range字段
    bool retrans=false;
    if(req.has_header("If-Range"))
    {
        string old_etag=req.get_header_value("If-Range");
        string eTagstr;
        GetEtag(bi,eTagstr);
        if(old_etag==eTagstr)
            retrans=true;
    }

    //写入body中
    if(retrans==false)
    {
        cloudBackup::FileUtil(bi.real_path).GetContent(&rsp.body);
        string eTagstr;
        GetEtag(bi,eTagstr);
        rsp.set_header("Accept-Ranges","bytes");
        rsp.set_header("ETag",eTagstr);
        rsp.set_header("Content-Type", "application/octet-stream");
        rsp.status=200;
    }
    else
    {
        cloudBackup::FileUtil(bi.real_path).GetContent(&rsp.body);
        string eTagstr;
        GetEtag(bi,eTagstr);
        rsp.set_header("Accept-Ranges","bytes");
        rsp.set_header("Content-Type", "application/octet-stream");
        //rsp.set_header("Contene-Range","bytes start-end/fsize");
        rsp.set_header("ETag",eTagstr);
        rsp.status=206;
    }
}

void Service::GetEtag(BackupInfo &info, string &str)
{
    cloudBackup::FileUtil fu(info.real_path);
    str=fu.FileName();
    str+="-";
    str+=to_string(info.fsize);
    str+="-";
    str+=to_string(info.mtime);
}

bool Service::RunModule()
{
    _server.Post("/upload",Upload);
    _server.Get("/listshow",ListShow);
    _server.Get("/",ListShow);
    _server.Get("/download/(.*)",Download);
    if(_server.listen("0.0.0.0",_server_port)==false)
    {
        cout<<__FILE__<<"-"<<__LINE__<<":"<<"error"<<endl;
        return false;
    }
    return true;
}
